#ifndef QUESTION_HPP
#define QUESTION_HPP

#include <QString>
#include <QStringList>
#include <vector>
#include <Random.hpp>

struct StaticChoiceQuestion{
    StaticChoiceQuestion(const char *utf8content,unsigned an,unsigned id_):content(QString::fromUtf8(utf8content)),answer(an),id(id_){}
    ~StaticChoiceQuestion(){}
    QString content;
    QStringList options;
    unsigned answer;
    unsigned id;
};

struct StaticJudgementQuestion{
    StaticJudgementQuestion(const char *utf8,unsigned an,unsigned i):content(QString::fromUtf8(utf8)),answer(an),id(i){}
    ~StaticJudgementQuestion(){}
    QString content;
    unsigned answer;
    unsigned id;
};

struct StaticBlankQuestion{
    StaticBlankQuestion(const char *c_,const char *a,unsigned i_):content(QString::fromUtf8(c_)),answer(QString::fromUtf8(a)),id(i_){}
    ~StaticBlankQuestion(){}
    QString content;
    QString answer;
    unsigned id;
};

struct PStaticChoiceQuestion{
    PStaticChoiceQuestion(StaticChoiceQuestion *q):question(q){}
    StaticChoiceQuestion *question;
};

struct PStaticJudgementQuestion{
    PStaticJudgementQuestion(StaticJudgementQuestion *q):question(q){}
    StaticJudgementQuestion *question;
};

struct ChoiceMapNode{
    char buffer[sizeof(StaticChoiceQuestion)];
    ChoiceMapNode *next;
    StaticChoiceQuestion *value;
};

struct JudgementMapNode{
    char buffer[sizeof(StaticJudgementQuestion)];
    JudgementMapNode *next;
    StaticJudgementQuestion *value;
};

struct BlankMapNode{
    char buffer[sizeof(StaticBlankQuestion)];
    BlankMapNode *next;
    StaticBlankQuestion *value;
};

enum{
    UORD_MAP_SIZE=256
};

class RandomQuestion{
public:
    RandomQuestion();
    ~RandomQuestion();
    int addQuestion(const char *fname);
    int addChoiceQuestionLib(std::istream *);
    int addJudgementQuestionLib(std::istream *);
    int addBlankQuestionLib(std::istream *);
    int addChallengeQuestionLib(std::istream *);
    int addShortAnswerQuestionLib(std::istream *);
    PStaticChoiceQuestion randomChooseChoiceQuestion();
    PStaticJudgementQuestion randomChooseJudgementQuestion();
    StaticBlankQuestion *randomChooseBlankQuestion();
    StaticBlankQuestion *randomChallengeQuestion();
    StaticBlankQuestion *randomShortAnswerQuestion();
    void outputChoiceQuestions(std::ostream &,bool withid=false);
    void outputJudgementQuestions(std::ostream &, bool withid=false);
    void outputBlankQuestions(std::ostream &, bool withid=false);
    void outputChallengeQuestions(std::ostream &,bool withid=false);
    unsigned currentId()const{return idgenerator;}
    SystemRandom &device(){return sys_randdevice;}
private:
    ChoiceMapNode choiceQuestionsData[UORD_MAP_SIZE];
    JudgementMapNode judgementQuestionsData[UORD_MAP_SIZE];
    BlankMapNode blankQuestionsData[UORD_MAP_SIZE];
    //BlankMapNode challengeQuestionsData[UORD_MAP_SIZE];
    std::vector<unsigned> choiceQuestions;
    std::vector<unsigned> judgementQuestions;
    std::vector<unsigned> blankQuestions;
    std::vector<unsigned> challengeQuestions;
    std::vector<unsigned> shortAnswerQuestions;
    Mt19937Random rand_device;
    SystemRandom sys_randdevice;
    unsigned idgenerator;
};

#endif // QUESTION_HPP
